;****************************************************************
;kernel/cpuid.asm
;CPU identification code for AWOS
;
;See LICENSE file included with this source for copyright
;information.
;****************************************************************

GLOBAL KiGetCpuClass

_type	db	0	;temporary storage for this function

KiGetCpuClass:
	jmp .386
.8086:
;;;;
;you can never be too pedantic
;just ensure we ARE running on a valid processor
;with new bootup.asm, someone *COULD* make a good hack to the kernel
;and get this code to run on an 8086
;;;;
	pushf			;push FLAGS on to stack
	pop	ax		;pop off to AX
	mov	cx, ax		;save in CX
	and	ax,0FFFFh	;clear bits 12-15 -- this will not work
				; on 808x processors because they are always set
	push	ax		;push new FLAGS on to stack
	popf			;pop off AX in to FLAGS
	pushf			;push new FLAGS on to stack
	and	ax,0F000h	;if bits 12-15 are set again,
	cmp	ax,0F000h	;this is an 808x processor
	jne	.286		;not 808x, go to 286 detection code
	mov	byte [_type],1	;yep
	push	sp		;double-check: push stack pointer
	pop	dx		;pop off stack pointer into DX
	cmp	dx,sp		;really 808x?
	jne	.ret		;return.
	mov	byte [_type],0Fh;unknown processor
	jmp	.ret
.286:
;;;;
;okay now we check for something more sane -- 286
;yay -- 286 instructions!
;;;;
	or	cx,0F000h	;try to set bits 12-15 -- this will not work
				; on 286 processors because they are always clear
	push	cx		;push new FLAGS
	popf			;pop new FLAGS off stack
	pushf			;push back new FLAGS
	pop	ax		;get new FLAGS in AX
	and	ax,0F000h	;if bits 12-15 are clear again,
	mov	byte [_type],2	;this is an 80286 processor
	jz	.ret
.386:
;;;;
;okay, this is where the real important code begins -- 386
;yay -- 386 instructions!
;;;;
	pushfd			;told ya I'd use 386 instructions
	pop	eax		;original EFLAGS in EAX
	mov	ecx,eax		;store in ECX for safe keeping
	xor	eax,40000h	;fiddle with AC bit -- not present in 386
	push	eax		;push new EFLAGS
	popfd			;pop new EFLAGS off stack
	pushfd			;push back new EFLAGS
	pop	eax		;get new EFLAGS in EAX
	xor	eax,ecx		;if AC bit not toggled
	mov	byte [_type],3	;this is an 80386 processor
	jz	.ret
.486:
;;;;
;THIS code is the REALLY important one, this code could actually be useful
;because people still HAVE 486s, at least moreso than the 386
;;;;
	push	ecx		;put original EFLAGS back
	popfd			;from the damage we did in .386
	mov	byte [_type],4	;it MUST be a 486
	mov	eax,ecx		;get original EFLAGS
	xor	eax,200000h	;change CPUID bit in EFLAGS
	push	eax		;push new EFLAGS
	popfd			;pop new EFLAGS
	pushfd			;push back new EFLAGS
	pop	eax		;get new EFLAGS in EAX
	xor	eax,ecx		;can't change CPUID bit
	je	.ret		;so it is a 486 below stepping 3
	mov	byte [_type],5	;yay -- CPUID supported!
.ret:
	mov	eax, [_type]	;put the type into EAX
	ret			;return!